package com.slfx.idgen.demo.idgen.customid;

import com.slfx.idgen.demo.idgen.exception.GenIdException;
import com.slfx.idgen.demo.idgen.properties.CustomIdProperties;
import com.slfx.idgen.demo.idgen.properties.IdgenProperties;
import com.slfx.idgen.demo.idgen.utils.JsonResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.loadbalancer.LoadBalancerClient;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

import java.time.LocalDateTime;
import java.util.Random;

public class CustomIdClient implements CommandLineRunner {

    private final Logger logger = LoggerFactory.getLogger(CustomIdClient.class);

    private static long currentSequence = 0;
    private static long maxSequence = 0;
    private long step = 1;

    //生成id前 先判断是否已经注册appName
    private boolean isRegisted;

    @Autowired(required = false)
    private LoadBalancerClient loadBalancerClient;

    private CustomIdProperties customIdProperties;

    private IdgenProperties idgenProperties;

    public CustomIdClient(CustomIdProperties customIdProperties,IdgenProperties idgenProperties) {
        this.customIdProperties = customIdProperties;
        this.idgenProperties = idgenProperties;
    }

    /**
     * 启动后检查生成id的appName申请了没有
      * @param args
     * @throws Exception
     */
    @Override
    public void run(String... args) throws Exception {
        this.isRegisted = isAppNameRegisted(idgenProperties.getAppName());
    }

    /**
     * 获取带前缀的id
     * @param prefix
     * @param length
     * @return
     */
    public String getNextStringId(String prefix, int length) {
        return prefix + getNextId(length);
    }

    /**
     * 获取自定义长度的id
     * @param length
     * @return
     */
    public synchronized long getNextId(int length) {
        if (!isRegisted) {
            throw new GenIdException("生成custom id前,需要先申请appName");
        }

        if (currentSequence + step > maxSequence) {
            getNextSequence(length);
        }
        currentSequence = currentSequence + step;
        return currentSequence;
    }

    /**
     * 获取下一段自增长的区间
     * @param length
     */
    private void getNextSequence(int length) {

        final String LOCATION = "/customId/sequence/next?appName=" + idgenProperties.getAppName() + "&&length=" + length;

        final String SERVICE_ID = "LOGISTICS-IDGEN-SERVER";

        ServiceInstance idgenInstance = loadBalancerClient.choose(SERVICE_ID);

        if (idgenInstance == null || idgenInstance.getUri() == null) {
            logger.error("没有找到id生成服务端:{}", SERVICE_ID);
            return;
        }

        RestTemplate restTemplate = createRestTemplate(2000, 2000);

        Sequence sequence = null;
        try {
            ResponseEntity<JsonResponse<Sequence>> responseEntity = restTemplate.exchange(idgenInstance.getUri() + LOCATION, HttpMethod.GET, HttpEntity.EMPTY, new ParameterizedTypeReference<JsonResponse<Sequence>>() {
            });
            JsonResponse<Sequence> response = responseEntity.getBody();
            if (response.getCode().equals("0")) {
                sequence = response.getData();
            } else {
                logger.error("获取下一区间id失败===>{}", LocalDateTime.now());
                logger.error(response.getMsg());
                return;
            }
        } catch (Exception e) {
            logger.error("获取下一区间id失败===>{}", LocalDateTime.now(), e);
            throw e;
        }

        maxSequence = sequence.getMaxSequence();

        currentSequence = sequence.getCurrentSequence();

        step = nextStep();
        logger.info("id增长step==========>{}", step);
    }

    private long nextStep() {
        Random random = new Random();
        return random.nextInt(9) + 1;
    }


    private boolean isAppNameRegisted(String appName) {
//        final String LOCATION = "/customId/isRegisted?appName=" + appName;
//
//        final String SERVICE_ID = "LOGISTICS-IDGEN-SERVER";
//
//        ServiceInstance idgenInstance = loadBalancerClient.choose(SERVICE_ID);
//
//        if (idgenInstance == null || idgenInstance.getUri() == null) {
//            logger.error("没有找到id生成服务端:{}", SERVICE_ID);
//            return false;
//        }
//
//        RestTemplate restTemplate = createRestTemplate(2000, 2000);
//
//        JsonResponse response = restTemplate.getForObject(idgenInstance.getUri() + LOCATION, JsonResponse.class);
//        assert response != null;
//        return response.getCode().equals("0");
        return true;
    }

      private RestTemplate createRestTemplate(int connectTimeout, int readTimeout) {
        SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
        requestFactory.setConnectTimeout(connectTimeout);
        requestFactory.setReadTimeout(readTimeout);

        return new RestTemplate(requestFactory);
    }
}
